#ifndef POSE_GL_H
#define POSE_GL_H

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <thread>
#include <array>
#include <mutex>
#include <functional>

#include "Coord3D.hpp"

class PoseGL
{
  public:
    PoseGL();
    virtual ~PoseGL();
    void ShowPose(const std::array<Cood3D,25> & pose);
    void SignalThreadRun(std::function<bool(const std::array<Cood3D,25>&)> func);
    void MultiThreadRun();
    bool isExit();
  private:
    std::mutex poseListMut;
    std::array<Cood3D,25> poseList;
    std::jthread UIthread;

    //OpenGL
    float cameraX, cameraY, cameraZ;
    float objCenterX=0,objCenterY=0,objCenterZ=0;
    GLuint renderingProgram1,renderingProgram2;
    GLuint vao[1];
    GLuint vbo[3];

    // variable allocation for display
    GLuint mvLoc, projLoc;
    int width, height, displayLoopi;
    float aspect;
    float tf;
    float routVal;
    glm::mat4 pMat, vMat,tMat, xflipMat,rMat,sMat, mMat, mvMat,lookat;
    std::mutex initMut;
    bool ExitFlag=false;
    bool bufferRefreshFlag=true;
    
    void Init(GLFWwindow* window);
    void display(GLFWwindow* window, double currentTime);
    void UIWork(std::stop_token token);
    void setupVertices();
    void setupLines();
    void setupIndex();
    static void window_size_callback(GLFWwindow* win, int newWidth, int newHeight);
    unsigned int LineIndex[48]={
      0, 1, // Nose ->Neck
      1, 2, // Neck ->RShoulder
      2, 3, // RShoulder->RElbow
      3, 4, // RElbow ->RWrist
      1, 5, // Neck ->LShoulder
      5, 6, // LShoulder->LElbow
      6, 7, // LElbow ->LWrist
      1, 8, // Neck ->MidHip
      8, 9, // MidHip ->RHip
      9, 10, // RHip ->RKnee
      10, 11, // RKnee ->RAnkle
      8, 12, // MidHip ->LHip
      12, 13, // LHip ->LKnee
      13, 14, // LKnee ->LAnkle
      0, 15, // Nose ->REye
      0, 16, // Nose ->LEye
      15, 17, // REye ->REar
      16, 18, // LEye ->LEar
      14, 19, // LAnkle ->LBigToe
      19, 20, // LBigToe ->LSmallToe
      14, 21, // LAnkle ->LHeel
      11, 22, // RAnkle ->RBigToe
      22, 23, // RBigToe ->RSmallToe
      11, 24, // RAnkle ->RHeel
    };
};

#endif
